package com.zhy.deploy.websocket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.maven.shared.invoker.InvokerLogger;

import javax.websocket.Session;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Objects;

@Slf4j
public class SocketMessage extends PrintStream implements InvokerLogger {

    private Session session;

    private int threshold;

    public SocketMessage(Session session, int threshold) {
        super(System.out);
        this.session = session;
        this.threshold = threshold;
    }

    @Override
    public void debug(String s) {
        this.log(InvokerLogger.DEBUG, s, null);
    }

    @Override
    public void debug(String s, Throwable throwable) {
        this.log(InvokerLogger.DEBUG, s, throwable);
    }

    @Override
    public void info(String s) {
        this.log(InvokerLogger.INFO, s, null);
    }

    @Override
    public void info(String s, Throwable throwable) {
        this.log(InvokerLogger.INFO, s, throwable);
    }

    @Override
    public void warn(String s) {
        this.log(InvokerLogger.WARN, s, null);
    }

    @Override
    public void warn(String s, Throwable throwable) {
        this.log(InvokerLogger.WARN, s, throwable);
    }

    @Override
    public void error(String s) {
        this.log(InvokerLogger.ERROR, s, null);
    }

    @Override
    public void error(String s, Throwable throwable) {
        this.log(InvokerLogger.ERROR, s, throwable);
    }

    @Override
    public void fatalError(String s) {
        this.log(InvokerLogger.FATAL, s, null);
    }

    @Override
    public void fatalError(String s, Throwable throwable) {
        this.log(InvokerLogger.FATAL, s, throwable);
    }

    @Override
    public boolean isDebugEnabled() {
        return this.threshold >= 4;
    }

    @Override
    public boolean isErrorEnabled() {
        return this.threshold >= 1;
    }

    @Override
    public boolean isFatalErrorEnabled() {
        return this.threshold >= 0;
    }

    @Override
    public boolean isInfoEnabled() {
        return this.threshold >= 3;
    }

    @Override
    public boolean isWarnEnabled() {
        return this.threshold >= 2;
    }

    @Override
    public int getThreshold() {
        return this.threshold;
    }

    @Override
    public void setThreshold(int threshold) {
        this.threshold = threshold;
    }

    @SneakyThrows
    public void println(String s) {
        synchronized (this) {
            info(s);
        }
    }

    public void close() {
        System.out.println("close……");
    }

    private void sendMessage(String message) {
        if (Objects.isNull(session)) {
            System.out.println(message);
            return;
        }

        if (log.isDebugEnabled()) {
            log.debug("send message sessionId【" + session.getId() + "】,message【" + message + "】");
        }

        try {
            if (session.isOpen()) {
                session.getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            log.error("日志打印失败……");
        }
    }

    private void log(int level, String message, Throwable error) {

        if (level <= this.threshold) {
            if (message != null || error != null) {
                StringBuffer buffer = new StringBuffer();
                switch (level) {
                    case 0:
                        buffer.append("[FATAL]");
                        break;
                    case 1:
                        buffer.append("[ERROR]");
                        break;
                    case 2:
                        buffer.append("[WARN]");
                        break;
                    case 3:
                        buffer.append("[INFO]");
                        break;
                    case 4:
                        buffer.append("[DEBUG]");
                }

                buffer.append(' ');
                if (message != null) {
                    buffer.append(message);
                }

                if (error != null) {
                    StringWriter writer = new StringWriter();
                    PrintWriter pWriter = new PrintWriter(writer);
                    error.printStackTrace(pWriter);
                    if (message != null) {
                        buffer.append('\n');
                    }

                    buffer.append("Error:\n");
                    buffer.append(writer.toString());
                }

                JSONObject obj = JSONUtil.createObj();
                obj.put("flag", level);
                obj.put("message", buffer.toString());

                sendMessage(obj.toString());

            }
        }
    }
}
